home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 15
/
Aminet 15 - Nov 1996.iso
/
Aminet
/
comm
/
bbs
/
s342q16.lha
/
libmsg.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-08-29
|
11KB
|
429 lines
/*
* * libmsg.c * * Common message handling
* functions for Citadel bulletin board system.
*/
/*
* * history * * 88Oct12 HAW Generalize
* getMessage() * 87Feb11 HAW Created.
*/
#include "ctdl.h"
/*
* * contents * * getMessage() load
* message into RAM * getMsgStr() reads a string out of
* message.buf * getMsgChar() returns successive chars off
* disk * startAt() setup to read a message off disk *
* unGetMsgChar() return a char to getMsgChar()
*/
struct mBuf mFile1,
mFile2;
MessageBuffer msgBuf,
tempMess;
FILE *msgfl,
*msgfl2;
static int GMCCache;
extern CONFIG cfg;
/*
* * getMessage() * * This function reads a message off disk into RAM. The
* source of the message * is controlled by the Source parameter; if the
* source is ctdlmsg.sys, then * a previous call to setUp has specified the
* message. * * FromNet - this indicates if the message is coming from a
* network-generated * temporary file (TRUE) or from ctdlmsg.sys (FALSE).
* If the latter then this * function must find the start of message within
* the current sector. Also, * the 'w' field of messages has different
* meanings depending on the source of * the message (messy, but useful). *
* * all - TRUE indicates the message text should be read in, FALSE
* indicates * reading should end when the 'M' field is encountered. * *
* ClearOthers - indicates all lists associated with msgBuf should be
* cleared * before the message is read in.
*/
char
getMessage(int (*Source) (void), char FromNet, char all, char ClearOthers)
{
int c;
char CC[CC_SIZE],
*d;
/*
* clear msgBuf out
*/
if (ClearOthers)
ZeroMsgBuffer(&msgBuf);
if (!FromNet)
{
/*
* only do this for messages from our own msgs
*/
do
{
c = getMsgChar();
}
while (c != 0xFF); /*
* find start of msg
*/
msgBuf.mbheadChar = mFile1.oldChar; /*
* record location
*/
msgBuf.mbheadSector = mFile1.oldSector;
getMsgStr(getMsgChar, msgBuf.mbId, NAMESIZE);
}
do
{
c = (*Source) ();
switch (c)
{
case 'A':
getMsgStr(Source, msgBuf.mbauth, sizeof msgBuf.mbauth);
break;
case 'D':
getMsgStr(Source, msgBuf.mbdate, NAMESIZE);
break;
case 'C':
getMsgStr(Source, msgBuf.mbtime, NAMESIZE);
break;
case 'M': /*
* just exit -- we'll read off disk
*/
break;
case 'N':
getMsgStr(Source, msgBuf.mboname, NAMESIZE);
while ((d = strchr(msgBuf.mboname, '_')) != NULL)
*d = ' ';
break;
case 'O':
getMsgStr(Source, msgBuf.mborig, NAMESIZE);
break;
case 'R':
getMsgStr(Source, msgBuf.mbroom, NAMESIZE);
break;
case 'S':
getMsgStr(Source, msgBuf.mbsrcId, NAMESIZE);
break;
case 'T':
getMsgStr(Source, msgBuf.mbto, sizeof msgBuf.mbto);
break;
case 'Q':
getMsgStr(Source, msgBuf.mbaddr, sizeof msgBuf.mbaddr);
break;
case 'X':
getMsgStr(Source, msgBuf.mbdomain, NAMESIZE);
break;
case 'P':
getMsgStr(Source, msgBuf.mbOther, O_NET_PATH_SIZE);
break;
case 'W':
getMsgStr(Source, CC, CC_SIZE);
if (ClearOthers)
AddData(&msgBuf.mbCC, strdup(CC), NULL, FALSE);
break;
case 'w':
if (FromNet)
{
getMsgStr(Source, CC, CC_SIZE);
if (ClearOthers)
AddData(&msgBuf.mbOverride, strdup(CC), NULL, FALSE);
}
else
{
/*
* now we can overload this -- 'w' is net only
*/
getMsgStr(Source, msgBuf.mbreply, NAMESIZE);
}
break;
/*
* yes, this is correct - we're overloading mbaddr.
*/
case 't':
getMsgStr(Source, msgBuf.mbaddr, sizeof msgBuf.mbaddr);
break;
case -1:
return FALSE;
default:
if (isprint(c))
{
/*
* save foreign fields
*/
msgBuf.mbtext[0] = c;
getMsgStr(Source, msgBuf.mbtext + 1, MAXTEXT - 5);
AddData(&msgBuf.mbForeign, strdup(msgBuf.mbtext), NULL, FALSE);
msgBuf.mbtext[0] = '\0';
}
else if (c == 0xFF && !FromNet)
{
/*
* Damaged msgBase
*/
unGetMsgChar(c);
}
break;
}
}
while (c != 'M' && isprint(c));
if (c == 'M')
{
if (all)
getMsgStr(Source, msgBuf.mbtext, MAXTEXT);
return TRUE;
}
return FALSE;
}
/*
* * getMsgStr() * * This function reads a string from the given source.
*/
void
getMsgStr(int (*Source) (void), char *dest, int lim)
{
int c;
while ((c = (*Source) ()) && c != EOF)
{
/*
* read the complete string
*/
if (lim)
{
/*
* if we have room then
*/
lim--;
if (c == '\r')
c = '\n';
*dest++ = c; /*
* copy char to buffer
*/
}
}
if (!lim)
dest--; /*
* Ensure not overwrite next door neighbor
*/
*dest = '\0'; /*
* tie string off with null
*/
}
/*
* * getMsgChar() * * This function returns sequential chars from
* CtdlMsg.Sys.
*/
int
getMsgChar()
{
long work;
int toReturn;
if (GMCCache)
{
/*
* someone did an unGetMsgChar() --return it
*/
toReturn = GMCCache;
GMCCache = '\0';
return (toReturn & 0xFF);
}
mFile1.oldChar = mFile1.thisChar;
mFile1.oldSector = mFile1.thisSector;
toReturn = mFile1.sectBuf[mFile1.thisChar];
toReturn &= 0xFF; /*
* Only want the lower 8 bits
*/
mFile1.thisChar = ++mFile1.thisChar % MSG_SECT_SIZE;
if (mFile1.thisChar == 0)
{
/*
* time to read next sector in:
*/
mFile1.thisSector = ++mFile1.thisSector % cfg.maxMSector;
work = mFile1.thisSector;
work *= MSG_SECT_SIZE;
fseek(msgfl, work, 0);
if (fread(mFile1.sectBuf, MSG_SECT_SIZE, 1, msgfl) != 1)
{
crashout("?nextMsgChar-read fail");
}
crypte(mFile1.sectBuf, MSG_SECT_SIZE, 0);
}
return (toReturn);
}
/*
* * startAt() * * This function sets the location to begin reading a
* message from. This is * usually only the sector, since byte offset within
* the sector is not * saved.
*/
void
startAt(FILE * whichmsg, struct mBuf *mFile, SECTOR_ID sect, int byt)
{
long temp;
GMCCache = '\0'; /*
* cache to unGetMsgChar() into
*/
if (sect >= cfg.maxMSector)
{
printf("?startAt s=%u,b=%d", sect, byt);
return; /*
* Don't crash anymore, just skip the msg
*/
}
mFile->thisChar = byt;
mFile->thisSector = sect;
temp = sect;
temp *= MSG_SECT_SIZE;
fseek(whichmsg, temp, 0);
if (fread(mFile->sectBuf, MSG_SECT_SIZE, 1, whichmsg) != 1)
{
crashout("?startAt read fail");
}
crypte(mFile->sectBuf, MSG_SECT_SIZE, 0);
}
/*
* * unGetMsgChar() * * This function returns (at most one) char to
* getMsgChar().
*/
void
unGetMsgChar(char c)
{
GMCCache = (int) c;
}
/*
* * ZeroMsgBuffer() * * This function zeroes a message buffer. This
* includes clearing lists out * legally, etc.
*/
void
ZeroMsgBuffer(MessageBuffer * msg)
{
memset(msg, 0, STATIC_MSG_SIZE);
KillList(&msg->mbCC);
KillList(&msg->mbOverride);
KillList(&msg->mbForeign);
msg->mbtext[0] = 0;
}
/*
* * InitMsgBase() * * This function opens the msg base(s), inits the msg
* buffers.
*/
void
InitMsgBase()
{
SYS_FILE name;
makeSysName(name, "ctdlmsg.sys", &cfg.msgArea);
openFile(name, &msgfl);
if (cfg.BoolFlags.mirror)
{
makeSysName(name, "ctdlmsg.sys", &cfg.msg2Area);
openFile(name, &msgfl2);
}
InitBuffers();
}
/*
* * InitBuffers() * * This function initializes the message buffers.
*/
void
InitBuffers()
{
static SListBase MsgBase =
{
NULL, ChkCC, NULL, free, strdup
};
copy_struct(MsgBase, msgBuf.mbCC);
copy_struct(MsgBase, msgBuf.mbOverride);
copy_struct(MsgBase, msgBuf.mbInternal);
copy_struct(MsgBase, msgBuf.mbForeign);
copy_struct(MsgBase, tempMess.mbOverride);
copy_struct(MsgBase, tempMess.mbCC);
copy_struct(MsgBase, tempMess.mbInternal);
copy_struct(MsgBase, tempMess.mbForeign);
msgBuf.mbtext = GetDynamic(MAXTEXT);
tempMess.mbtext = GetDynamic(MAXTEXT);
}
/*
* * findMessage() * * This function will get all set up to do something
* with a message.
*/
char
findMessage(SECTOR_ID loc, MSG_NUMBER id, char ClearOthers)
{
MSG_NUMBER here;
id &= S_MSG_MASK;
startAt(msgfl, &mFile1, loc, 0);
do
{
getMessage(getMsgChar, FALSE, FALSE, ClearOthers);
here = atol(msgBuf.mbId);
}
while (here != id && mFile1.thisSector == loc);
if (here != id)
mPrintf("Ooops, couldn't find %ld @ %d.\n ", id, loc);
return (char) ((here == id));
}
/*
* * Preliminary comments & code for CC feature in C-86. * * Comments and
* notes. * * o Numerous requests for this feature tend to make it valuable.
* * * o Suggest we have a field which may have multiple instances in any
* message. * This is the 'cc' field. Suggest further that it be 2 *
* NAMESIZE bytes * long in order to allow node designators. * * o
* Implementation: The getMessage() function should build a linked list *
* (possibly generic list: libarch.c) as it reads in a message of each * CC
* recipient. Will need to have a disposal function for this list as *
* each message is disposed of. May take a little code massage to make *
* sure we hit all the high points. * * o Only available for Mail>. * o
* (Since getMessage handles all the forms of getting messages from any *
* source, this handles all the net forms, too.) * * o Code massage points
* not otherwise covered in this file: * - Held Messages. * - Interrupted
* Messages(!). * - getMessage(). * - putMessage() - how do we handle the
* analog to noteMessage()? New * parameter? * * o Network provisions *
* - Net support not present for this type of message. * - New field, net
* only: Recipient override. Indicates who mail is to be * given access
* to this message, may (easily) exclude recipient specified * in the
* mbto[] field. New field named mboverride[NAMESIZE * 2]. * - Like mbCC,
* should be handled as list with multiple instances. * - Check for mail
* should check this list instead of mbto iff mboverride * is present. *
* - mboverride fields will not contain node designators (initially). *
* mbCC fields will, where necessary. * * o Other comments and thoughts about
* design, etc. * - Unlogged users should not have access. * - List of CC
* users should be accessible to message writer. * - Able to remove someone
* from list of CC users??? * - Net designation. Use STadel's '@'
* convention? Seems logical. * - NEED FORMAT FOR DISPLAY OF FINISHED &
* DELIVERED MESSAGE! * - NETHACK3.MAN will need updating. * - * * ALSO
* SEE CC.C.
*/
/*
* * ChkCC() * * This will see if the two records are identical. This is
* used for list * searches.
*/
void *
ChkCC(char *d1, char *d2)
{
return (strCmpU(d1, d2) == SAMESTRING) ? d1 : NULL;
}